home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 06 - 1990 / 06.04 Apr 90 / DialogQuake ƒ / dialogQuake INIT.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-06  |  6.2 KB  |  280 lines  |  [TEXT/KAHL]

  1. /* dialogQuake INIT.c      5 June 89
  2.  *
  3.  * written by Mike Scanlin
  4.  * inspiration by Andy Jeffrey
  5.  * unwilling testing by "Goobs" Galvan
  6.  *
  7.  * INIT that installs a patch on _ModalDialog that will,
  8.  * when _ModalDialog is called, install a tail patch on
  9.  * _GetNextEvent that causes the frontmost window to move
  10.  * around a bit (making it hard to click on items with any
  11.  * real accuracy). The patch to _GetNextEvent is removed
  12.  * before _ModalDialog returns and the patch to _ModalDialog
  13.  * can be removed by typing cmd-option-shift-tab while a
  14.  * modal dialog is frontmost.
  15.  */
  16.  
  17. /* traps we patch */
  18. #define    ModalDialog        0xA991
  19. #define    GetNextEvent    0xA970
  20.  
  21. /* uses a bit of self-modifying code */
  22. #define    JMP                0x4EF9
  23.  
  24. #define    TAB_KEY            0x09
  25. #define    memFullErr        -108
  26.  
  27. void    main(void);
  28.  
  29. void    main()
  30. {
  31.     asm    {
  32.  
  33. /* the next 20 or so lines are the only ones that get
  34.  * executed during installation. They get some space in
  35.  * the system heap for the patches and then patch
  36.  * _ModalDialog. */
  37.  
  38. /* save register */
  39.                 move.l    D4,-(SP)
  40.                 
  41. /* get the old trap address */
  42.                 move    #ModalDialog,D0
  43.                 _GetTrapAddress
  44.  
  45. /* set the address for the JMP instruction that calls
  46.  * the original trap */
  47.                 lea        @origMD,A1
  48.                 move.l    A0,(A1)
  49.  
  50. /* get some space in the system heap for our patches
  51.  * (note that this space is for both patches) */
  52.                 lea        @last,A0
  53.                 lea        @modalDialogPatch,A1
  54.                 suba.l    A1,A0
  55.                 move.l    A0,D0
  56.                 move.l    D0,D4
  57.                 _NewPtr    SYS
  58.  
  59. /* if there's not enough memory then abort the
  60.  * installation */
  61.                 cmpi    #memFullErr,D0
  62.                 beq.s    @noPatch
  63.     
  64. /* save address for _BlockMove */                
  65.                 move.l    A0,-(SP)
  66.  
  67. /* set the trap address to the space we just got */
  68.                 move    #ModalDialog,D0
  69.                 _SetTrapAddress
  70.  
  71. /* now move our patch into place */
  72.                 lea        @modalDialogPatch,A0        
  73.                 move.l    (SP)+,A1
  74.                 move.l    D4,D0
  75.                 _BlockMove
  76.                 
  77. @noPatch
  78.  
  79. /* restore register and exit installation code */
  80.                 move.l    (SP)+,D4
  81.                 rts
  82.  
  83. /********************************************
  84.  * Here's the new _ModalDialog. It first installs
  85.  * a tail patch on _GetNextEvent and then calls
  86.  * the existing _ModalDialog. On exit this patch
  87.  * will unpatch the _GetNextEvent patch.
  88.  *******************************************/
  89.  
  90. @modalDialogPatch    
  91.  
  92. /* save the original _GetNextEvent address */
  93.                 move    #GetNextEvent,D0
  94.                 _GetTrapAddress
  95.  
  96. /* set the address for the JMP instruction that calls
  97.  * the original trap */
  98.                 lea        @origGNE,A1
  99.                 move.l    A0,(A1)
  100.  
  101. /* patch _GetNextEvent */
  102.                 lea        @getNextEventPatch,A0
  103.                 move    #GetNextEvent,D0
  104.                 _SetTrapAddress
  105.  
  106. /* pop the original return address and save it */
  107.                 lea        @exitMD,A0
  108.                 move.l    (SP)+,(A0)
  109.  
  110. /* set the return address to our patch */
  111.                 pea        @tailMDPatch
  112.             
  113. /* the nops get filled with the address of the original
  114.  * _ModalDialog */
  115.                 dc        JMP
  116. @origMD            nop
  117.                 nop
  118.  
  119. /* _ModalDialog returns here */
  120.  
  121. @tailMDPatch
  122.  
  123. /* remove the patch to _GetNextEvent */
  124.                 lea        @origGNE,A0
  125.                 move.l    (A0),A0
  126.                 move    #GetNextEvent,D0
  127.                 _SetTrapAddress
  128.  
  129. /* return to the place that called _ModalDialog */
  130.                 dc        JMP
  131. @exitMD            nop
  132.                 nop
  133.             
  134.                 
  135. /********************************************
  136.  * Here's the new _GetNextEvent. If a random
  137.  * amount of time has passed then call 
  138.  * _MoveWindow to move the frontmost window
  139.  * (a modal dialog) in a random direction.
  140.  *******************************************/
  141.  
  142. @getNextEventPatch
  143.  
  144. /* pop the original return address and save it */
  145.                 lea        @exitGNE,A0
  146.                 move.l    (SP)+,(A0)
  147.  
  148. /* save pointer to the event record so we can get to
  149.  * it when the real _GetNextEvent returns */
  150.                 lea        @eventRecPtr,A0
  151.                 move.l    (SP),(A0)
  152.  
  153. /* set the return address to our patch */
  154.                 pea        @tailGNEPatch
  155.                 
  156. /* the nops get filled with the address of the original
  157.  * _GetNextEvent */
  158.                 dc        JMP
  159. @origGNE        nop
  160.                 nop
  161.  
  162. /* _GetNextEvent returns here */
  163.  
  164. @tailGNEPatch
  165.  
  166. /* save registers */
  167.                 movem.l    D0-D2/A0-A2,-(SP)
  168.  
  169. /* if they don't want us around, then exit */
  170.                 lea        @noMoreHassle,A0
  171.                 tst        (A0)
  172.                 bne     @goodBye
  173.  
  174. /* check if the event is a keyDown event */                
  175.                 lea        @eventRecPtr,A0
  176.                 move.l    (A0),A0
  177.                 move    OFFSET(EventRecord,what)(A0),D0
  178.                 cmpi    #keyDown,D0
  179.                 bne.s    @noKeyDown
  180.  
  181. /* it's a keydown, but is it the special remove-us key? */
  182.                 move.l    OFFSET(EventRecord,message)(A0),D0
  183.                 cmpi.b    #TAB_KEY,D0
  184.                 bne.s    @noKeyDown
  185.                 move    OFFSET(EventRecord,modifiers)(A0),D0
  186.                 andi    #cmdKey + optionKey + shiftKey,D0
  187.                 eori    #cmdKey + optionKey + shiftKey,D0
  188.                 bne.s    @noKeyDown
  189.  
  190. /* they don't like us any more so remove ourself. First beep
  191.  * to let them know that we got the message to go away */
  192.                 move    #1,-(SP)
  193.                 _SysBeep
  194.  
  195. /* set a flag so we know not to bother the nice user any more */
  196.                 lea        @noMoreHassle,A0
  197.                 move    #1,(A0)
  198.  
  199. /* move the frontmost window to a nice place in case it was
  200.  * partially moved off the screen by _MoveWindow */
  201.                 move.l    WindowList,-(SP)
  202.                 move    #30,-(SP)
  203.                 move    #30,-(SP)
  204.                 bra.s    @moveToUpperLeft
  205.  
  206. @noKeyDown
  207.  
  208. /* has the timer expired? */
  209.                 lea        @timer,A0
  210.                 subi    #1,(A0)
  211.                 bpl.s    @goodBye
  212.  
  213. /* reset the timer to wait a random amount of time before
  214.  * expiring again */
  215.                 subq    #2,SP
  216.                 _Random
  217.                 move    (SP)+,D0
  218.  
  219. /* note: make the 0x3F smaller to move the window more often */
  220.                 andi    #0x3F,D0
  221.                 lea        @timer,A0
  222.                 move    D0,(A0)
  223.  
  224. /* push a WindowPtr for _MoveWindow. Note: this does not
  225.  * check for Ghost Windows */
  226.                 move.l    WindowList,A2
  227.                 move.l    A2,-(SP)
  228.  
  229. /* get a couple of random numbers in the range [-7..+7] */
  230.                 subq    #2,SP
  231.                 _Random
  232.                 move    (SP)+,D1
  233.                 move    D1,D2
  234.                 asr        #8,D1
  235.                 andi    #0x8007,D1
  236.                 bpl.s    @2
  237.                 bclr    #15,D1
  238.                 neg        D1
  239. @2                ext        D2
  240.                 andi    #0x8007,D2
  241.                 bpl.s    @3
  242.                 bclr    #15,D2
  243.                 neg        D2
  244. @3
  245.  
  246. /* push a random h coordinate */                
  247.                 move    OFFSET(GrafPort,portBits)+OFFSET(BitMap,bounds)+OFFSET(Rect,left)(A2),D0
  248.                 neg        D0
  249.                 add        D1,D0
  250.                 move    D0,-(SP)
  251.                 
  252. /* push a random v coordinate */                
  253.                 move    OFFSET(GrafPort,portBits)+OFFSET(BitMap,bounds)+OFFSET(Rect,top)(A2),D0
  254.                 neg        D0
  255.                 add        D2,D0
  256.                 move    D0,-(SP)
  257.                 
  258. @moveToUpperLeft
  259.                 sf        -(SP)
  260.                 _MoveWindow
  261.                 
  262. @goodBye
  263.  
  264. /* restore registers */
  265.                 movem.l    (SP)+,D0-D2/A0-A2
  266.                 
  267. /* return to _ModalDialog */
  268.                 dc        JMP
  269. @exitGNE        nop
  270.                 nop
  271.  
  272. /* variables */
  273. @noMoreHassle    dc        0
  274. @eventRecPtr    dc.l    0
  275. @timer            dc        0
  276.  
  277. @last
  278.     }
  279. }
  280.